home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Systemmonitors
/
FreeMap
/
FreeMapSrc
/
freemap.c
next >
Wrap
C/C++ Source or Header
|
1996-09-26
|
12KB
|
505 lines
/*
*
* DISCLAIMER:
*
* This program is provided as a service to the programmer
* community to demonstrate one or more features of the Amiga
* personal computer. These code samples may be freely used
* for commercial or noncommercial purposes.
*
* Commodore Electronics, Ltd ("Commodore") makes no
* warranties, either expressed or implied, with respect
* to the program described herein, its quality, performance,
* merchantability, or fitness for any particular purpose.
* This program is provided "as is" and the entire risk
* as to its quality and performance is with the user.
* Should the program prove defective following its
* purchase, the user (and not the creator of the program,
* Commodore, their distributors or their retailers)
* assumes the entire cost of all necessary damages. In
* no event will Commodore be liable for direct, indirect,
* incidental or consequential damages resulting from any
* defect in the program even if it has been advised of the
* possibility of such damages. Some laws do not allow
* the exclusion or limitation of implied warranties or
* liabilities for incidental or consequential damages,
* so the above limitation or exclusion may not apply.
*
*/
/*****************************************************************************
*
* FreeMap program creates a visual diagram of free memory
*
* =Robert J. Mical=
* 9 January 1986
*
* Copyright (C) 1986, COMMODORE-AMIGA, INC.
* All Rights Reserved
*
****************************************************************************/
#include "freemap.h"
#define SCREENWIDTH 320
#define SCREENHEIGHT 36
#define STARTLINE 6
#define STARTCOLUMN (2 + 4)
#define LEFTOFFSET 6
#define MENU_INFO 2
#define MENU_REDISPLAY 1
#define MENU_QUIT 0
#define SCREENBYTEWIDTH 40
#define MAPBYTEWIDTH 32 /* must be a power of two */
#define MAX_BLOCK_COUNT ((512 * 1024) >> 6)
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;
struct TextAttr SafeFont =
{
"topaz.font",
8,
0,
0,
};
struct IntuiText PleaseText =
{
0, 1,
JAM2,
1, 1,
NULL,
"Please",
NULL,
};
struct MenuItem PleaseItem =
{
NULL,
0, 0,
88, 9,
ITEMTEXT | ITEMENABLED | HIGHCOMP,
0,
(APTR)&PleaseText,
NULL,
0,
NULL,
NULL,
};
struct Menu MapMenus[] =
{
{
NULL,
10, 0,
48, 0,
MENUENABLED,
"Info",
&PleaseItem,
},
{
&MapMenus[0],
58, 0,
88, 0,
MENUENABLED,
"Redisplay",
&PleaseItem,
},
{
&MapMenus[1],
146, 0,
48, 0,
MENUENABLED,
"Quit",
&PleaseItem,
},
};
struct NewScreen MapScreen =
{
0, 200 - SCREENHEIGHT,
SCREENWIDTH, SCREENHEIGHT, 1,
0, 1,
NULL,
CUSTOMSCREEN,
&SafeFont,
NULL,
NULL,
NULL,
};
struct NewWindow MapWindow =
{
LEFTOFFSET, 0,
(MAPBYTEWIDTH << 3) + 4, SCREENHEIGHT,
-1, -1,
MENUPICK | MENUVERIFY,
SMART_REFRESH | BACKDROP | BORDERLESS | NOCAREREFRESH,
NULL,
NULL,
NULL,
NULL,
NULL,
0, 0, 0, 0,
CUSTOMSCREEN,
};
struct Screen *MyScreen;
struct Window *MyWindow;
SHORT BitsAvailable;
SHORT BlockCount;
BYTE BitsValue;
SHORT WidthIndex;
UBYTE *MemBlock;
UBYTE *MapPointer;
ShiftMask[8] =
{
0xFF,
0X01,
0x03,
0x07,
0x0F,
0x1F,
0x3F,
0x7F,
};
RestartWindow()
/* This routine clears the window and then draws the border */
{
SetRast(MyWindow->RPort, 0);
Move(MyWindow->RPort, 0, 0);
Draw(MyWindow->RPort, 0, SCREENHEIGHT - 1);
Draw(MyWindow->RPort, (MAPBYTEWIDTH << 3)+4-1, SCREENHEIGHT - 1);
Draw(MyWindow->RPort, (MAPBYTEWIDTH << 3) + 4 - 1, 0);
Draw(MyWindow->RPort, 0, 0);
}
BumpMapPointer()
/* This routine bumps the MapPointer variable, which variable contains the
* pointer to the byte in the Screen's BitMap which is to receive the
* next FreeMap bits.
*/
{
WidthIndex++;
if (WidthIndex == MAPBYTEWIDTH)
{
/* We're at the right edge of the map window, so skip ahead
* to the left edge of the next line
*/
WidthIndex = 0;
MapPointer += (SCREENBYTEWIDTH - MAPBYTEWIDTH + 1);
}
else MapPointer++;
}
ShiftInBits(bitcount)
SHORT bitcount;
/* This routine "shifts" the next set of bits into the memory map */
{
SHORT shift, bytecount;
if (BitsAvailable & 0x7)
{
/* There's less than a whole byte available, so we must start
* by shifting. Get the shift amount, which will be either all
* of the bits that are available, or the block count if it's less
* than the count of the available bits
*/
if (bitcount > BitsAvailable) shift = BitsAvailable;
else shift = bitcount;
/* Shift the current contents of this byte of the map
* out of the way of our new bits.
*/
*MapPointer <<= shift;
/* The above shift shifts zero bits in from the right.
* If the current BitsValue is clear, leave them zero, else set our
* new bits.
*/
if (BitsValue) *MapPointer |= ShiftMask[shift];
/* Reduce the block count by the number of bits we just arranged */
bitcount -= shift;
/* if we've used up this memory map byte, advance to the next one */
if ((BitsAvailable -= shift) == 0)
{
BitsAvailable = 8;
BumpMapPointer();
}
}
/* Now that we've taken care of any partially completed Map bytes,
* let's check for any whole bytes that we can set (speed!)
*/
bytecount = bitcount >> 3;
while (bytecount)
{
*MapPointer = BitsValue;
BumpMapPointer();
bytecount--;
}
/* Finally, do any remaining bitcount bits to be set */
if (bitcount &= 0x7)
{
*MapPointer = BitsValue; /* Cheating, in a sense, but FAST! */
BitsAvailable = 8 - bitcount;
}
}
SHORT FindFreeBlock()
/* This routine feels through the memory-free list, looking for a block
* of free memory that is big enough to qualify as being a block.
* A block starts on 64-byte boundaries and is 64-bytes wide. For a
* block to be considered "free" all of the 64 bytes must be free
*/
{
SHORT firstwholeblock, nextrealblock;
FOREVER
{
if (MemBlock == 0) return(0);
firstwholeblock = (LONG)(MemBlock + 63) >> 6;
nextrealblock = (LONG)( MemBlock
+ ((struct MemChunk *)MemBlock)->mc_Bytes ) >> 6;
MemBlock = (UBYTE *)((struct MemChunk *)MemBlock)->mc_Next;
if (firstwholeblock < nextrealblock)
{
BlockCount = nextrealblock - firstwholeblock;
return(firstwholeblock);
}
}
}
SetTimer(sec, micro, timermsg)
ULONG sec, micro;
struct IOStdReq *timermsg;
/* This routine simply sets the timer to interrupt us after secs.micros */
{
timermsg->io_Command = TR_ADDREQUEST; /* add a new timer request */
timermsg->io_Actual = sec; /* seconds */
timermsg->io_Length = micro; /* microseconds */
SendIO(timermsg); /* post a request to the timer */
}
main()
{
struct MsgPort *timerport;
struct IOStdReq *timermsg;
struct MemHeader *MemHeader;
SHORT NextFreeBlock, NextTakenBlock;
ULONG wakeupbits, timerbit, windowbit;
struct IntuiMessage *message;
ULONG class;
USHORT code;
BOOL Redisplay;
if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
"intuition.library", 0)) == 0)
{
printf("NO LIBRARY");
goto EXITING;
}
if ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0)) == 0)
{
printf("NO LIBRARY");
goto EXITING;
}
if ((MyScreen = (struct Screen *)OpenScreen(&MapScreen)) == NULL)
{
printf("NO SCREEN");
goto EXITING;
}
ShowTitle(MyScreen, FALSE);
SetRGB4(&MyScreen->ViewPort, 0, 15, 12, 8);
SetRGB4(&MyScreen->ViewPort, 1, 8, 0, 0);
MapWindow.Screen = MyScreen;
if ((MyWindow = (struct Window *)OpenWindow(&MapWindow)) == NULL)
{
printf("NO WINDOW");
goto EXITING;
}
SetMenuStrip(MyWindow, &MapMenus[2]);
SetFont(MyWindow->RPort, OpenFont(&SafeFont));
Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 18);
Text(&MyScreen->RastPort, "512K", 4);
Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 26);
Text(&MyScreen->RastPort, "MEMORY", 6);
Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 34);
Text(&MyScreen->RastPort, "MAP", 3);
RestartWindow();
timerport = (struct MsgPort *)CreatePort(0, 0);
if (timerport == 0) goto EXITING;
timermsg = (struct IOStdReq *)CreateStdIO(timerport);
if (timermsg == 0) goto EXITING;
if (OpenDevice(TIMERNAME, UNIT_VBLANK, timermsg, 0) != 0)
goto EXITING;
timerbit = 1 << timerport->mp_SigBit;
windowbit = 1 << MyWindow->UserPort->mp_SigBit;
SetTimer(2, 0, timermsg);
Redisplay = TRUE;
FOREVER
{
if (Redisplay)
{
/* This program draws the memory map information right into
* the BitMap of the Screen, rather than using the graphics
* support library routines to draw into the Window.
* There is nothing illegal or immoral about doing this, but
* is does require a thorough knowledge of how Intuition and
* the graphics library create and manipulate the display.
* In other words, this is *not* something that the novice
* will want to do lightly, but the soon-to-be-expert may
* want to examine as an example of how to do meta-graphics
* in the Amiga window environment.
*/
MapPointer = MyScreen->RastPort.BitMap->Planes[0];
MapPointer += (SCREENBYTEWIDTH * 2 + 1);
Forbid();
do
MemHeader = (struct MemHeader *)SysBase->MemList.lh_Head;
while ((MemHeader->mh_Attributes & MEMF_CHIP) == 0);
MemBlock = (UBYTE *)MemHeader->mh_First;
BitsAvailable = 8;
WidthIndex = 0;
NextTakenBlock = 0;
do
{
if (NextFreeBlock = FindFreeBlock())
{
BitsValue = 0;
ShiftInBits(NextFreeBlock - NextTakenBlock);
BitsValue = -1;
ShiftInBits(BlockCount);
NextTakenBlock = NextFreeBlock + BlockCount;
}
else ShiftInBits(MAX_BLOCK_COUNT - NextTakenBlock);
}
while (MemBlock);
if (NextTakenBlock < MAX_BLOCK_COUNT)
{
BitsValue = 0;
ShiftInBits(MAX_BLOCK_COUNT - NextTakenBlock);
}
Permit();
}
wakeupbits = Wait(timerbit | windowbit);
if (wakeupbits & timerbit)
{
GetMsg(timerport); /* this does nothing more than "clear" */
SetTimer(2, 0, timermsg);
}
if (wakeupbits & windowbit)
{
message = (struct IntuiMessage *)GetMsg(MyWindow->UserPort);
class = message->Class;
code = message->Code;
ReplyMsg(message);
switch (class)
{
case MENUVERIFY:
Redisplay = FALSE;
break;
case MENUPICK:
switch (MENUNUM(code))
{
case MENU_INFO:
RestartWindow();
Move(MyWindow->RPort,
STARTCOLUMN, STARTLINE);
Text(MyWindow->RPort,
"Each pixel represents 64 bytes.", 31);
Move(MyWindow->RPort,
STARTCOLUMN + 20, STARTLINE + 9);
Text(MyWindow->RPort,
"If all bytes are free, the", 26);
Move(MyWindow->RPort,
STARTCOLUMN, STARTLINE + 18);
Text(MyWindow->RPort,
"pixel is dark, else it's light.", 31);
Move(MyWindow->RPort,
STARTCOLUMN + 20, STARTLINE + 28);
Text(MyWindow->RPort,
"This trinket by =RJMical=", 26);
break;
case MENU_REDISPLAY:
RestartWindow();
case NOMENU:
Redisplay = TRUE;
break;
case MENU_QUIT:
goto EXITING;
}
}
}
}
EXITING:
if (MyWindow) CloseWindow(MyWindow);
if (MyScreen) CloseScreen(MyScreen);
if (timerport)
{
Wait(timerbit);
GetMsg(timerport);
CloseDevice(timermsg);
DeleteStdIO(timermsg);
DeletePort(timerport);
}
}